﻿using System;
using System.Data;
using System.Configuration;
using DGZfP.EventPublisher.Calendar;
using Google.GData.Calendar;
using Microsoft.VisualStudio.TestTools.UnitTesting;


namespace DGZfP.EventPublisher.CalendarTest
{


    /// <summary>
    ///Dies ist eine Testklasse für "GEventAdapterTest" und soll
    ///alle GEventAdapterTest Komponententests enthalten.
    ///</summary>
    [TestClass()]
    public class GEventAdapterTest
    {


        private TestContext testContextInstance;

        private int CounterElementMissingInFirstList;
        private int CounterElementMissingInSecondList;
        private int CounterElementIsInBothLists;

        /// <summary>
        ///Ruft den Testkontext auf, der Informationen
        ///über und Funktionalität für den aktuellen Testlauf bietet, oder legt diesen fest.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Zusätzliche Testattribute
        // 
        //Sie können beim Verfassen Ihrer Tests die folgenden zusätzlichen Attribute verwenden:
        //
        //Mit ClassInitialize führen Sie Code aus, bevor Sie den ersten Test in der Klasse ausführen.
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Mit ClassCleanup führen Sie Code aus, nachdem alle Tests in einer Klasse ausgeführt wurden.
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Mit TestInitialize können Sie vor jedem einzelnen Test Code ausführen.
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Mit TestCleanup können Sie nach jedem einzelnen Test Code ausführen.
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        [TestMethod()]
        public void BasicGoogleEventTests()
        {

            var target = new EventByGoogleCalendarEvent();
            string content = "content";
            string title = "title";
            DateTime start = DateTime.Today;
            DateTime end = start.AddDays(1);
            bool allday = true;
            int id = 4711;

            target.Title = title;
            target.Content = content;
            target.StartDate = start;
            target.EndDate = end;
            target.AllDay = allday;
            target.ID = id.ToString ();

            Assert.AreEqual(target.Title, title);
            Assert.AreEqual(target.Content, content);
            Assert.AreEqual(target.StartDate, start);
            Assert.AreEqual(target.EndDate, end);
            Assert.AreEqual(target.AllDay, allday);
            Assert.AreEqual(target.ID, id);

            CalendarService myService = GetService();

            Uri postUri = new Uri(String.Format("http://www.google.com/calendar/feeds/{0}/private/full", GetFeedID()));

            // Send the request and receive the response:
            EventEntry insertedEntry = (EventEntry)myService.Insert(postUri, target.EventEntry);

            target = new EventByGoogleCalendarEvent(insertedEntry);
            Assert.AreEqual(target.Title, title);
            Assert.AreEqual(target.Content, content);
            Assert.AreEqual(target.StartDate, start);
            Assert.AreEqual(target.EndDate, end);
            Assert.AreEqual(target.AllDay, allday);
            Assert.AreEqual(target.ID, id);

            myService.Delete(insertedEntry);
        }

        [TestMethod()]
        public void BasicDataSetTests()
        {
            var dt = NewDataTable();

            IEvent target = new EventByDataRow(dt.NewRow());

            string content = "content";
            string title = "title";
            DateTime start = DateTime.Today;
            DateTime end = start.AddDays(1);
            bool allday = true;
            int id = 4711;


            target.Title = title;
            target.Content = content;
            target.StartDate = start;
            target.EndDate = end;
            target.AllDay = allday;
            target.ID = id.ToString();


            Assert.AreEqual(target.Title, title);
            Assert.AreEqual(target.Content, content);
            Assert.AreEqual(target.StartDate, start);
            Assert.AreEqual(target.EndDate, end);
            Assert.AreEqual(target.AllDay, allday);
            Assert.AreEqual(target.ID, id);

        }

        [TestMethod()]
        public void ListTest()
        {
            var dt = FillEventTable(10);
            int i = 0;
            foreach (IEvent target in new EventsByDataTable(dt))
            {
                Assert.AreEqual(target.ID, i);
                i++;
            }
        }

        [TestMethod()]
        public void FeedTest()
        {
            //add one item to feed 

            EventByGoogleCalendarEvent target = new EventByGoogleCalendarEvent();

            string content = "content";
            string title = "title";
            DateTime start = DateTime.Today;
            DateTime end = start.AddDays(1);
            bool allday = true;
            int id = 4711;


            target.Title = title;
            target.Content = content;
            target.StartDate = start;
            target.EndDate = end;
            target.AllDay = allday;
            target.ID = id.ToString ();

            CalendarService myService = GetService();

            Uri postUri = new Uri(String.Format("http://www.google.com/calendar/feeds/{0}/private/full", GetFeedID()));

            EventEntry insertedEntry = (EventEntry)myService.Insert(postUri, target.EventEntry);

            bool itemfound = false;
            foreach (IEvent entry in new EventsByGoogleCalendarFeed(myService, GetFeedID()))
            {
                if (entry.ID == "4711") itemfound = true;
            }

            Assert.IsTrue(itemfound);

            //delete it again
            myService.Delete(insertedEntry);
        }

        [TestMethod()]
        public void ListComparerTest()
        {
            var table1 = FillEventTable(0, 10);
            var table2 = FillEventTable(5, 10);

            var lc = new ListsComparer<IEvent>();
            lc.ListsCompareEvent += new ListsCompareEventHandler<IEvent>(CountListCompareEvents);
            CounterElementIsInBothLists = 0;
            CounterElementMissingInFirstList = 0;
            CounterElementMissingInSecondList = 0;
            lc.Compare(new EventsByDataTable(table1), new EventsByDataTable(table2),
                delegate(IEvent a, IEvent b)
                {
                    return a.ID == b.ID;
                });
            Assert.AreEqual(5, CounterElementIsInBothLists);
            Assert.AreEqual(5, CounterElementMissingInFirstList);
            Assert.AreEqual(5, CounterElementMissingInSecondList);
        }


        [TestMethod()]
        public void SyncGoogleCalendar()
        {
            var table1 = FillEventTable(4, 3);
            var masterEvents = new EventsByDataTable(table1, "TestContext");


            CalendarService myService = GetService();
            var slaveEvents = new EventsByGoogleCalendarFeed(myService, GetFeedID(), DateTime.Today.AddDays(-1), "TestContext");

            slaveEvents.SynchroniseEvents(masterEvents);
            table1 = FillEventTable(1, 1);
            masterEvents = new EventsByDataTable(table1, "TestContext");
            slaveEvents.SynchroniseEvents(masterEvents);


        }

        [TestMethod()]
        public void ListComparerTest2()
        {
            var table1 = FillEventTable(0, 10,true);

            var table2 = FillEventTable(5, 10,true);

            var lc = new ListsComparer<IEvent>();
            lc.ListsCompareEvent += new ListsCompareEventHandler<IEvent>(CountListCompareEvents);
            CounterElementIsInBothLists = 0;
            CounterElementMissingInFirstList = 0;
            CounterElementMissingInSecondList = 0;
            lc.Compare(new EventsByDataTable(table1), new EventsByDataTable(table2),
                delegate(IEvent a, IEvent b)
                {
                    return a.ID == b.ID;
                });
            Assert.AreEqual(5, CounterElementIsInBothLists);
            Assert.AreEqual(5, CounterElementMissingInFirstList);
            Assert.AreEqual(5, CounterElementMissingInSecondList);
        }





        #region Help Methods
        private void CountListCompareEvents(object sender, ListsCompareEventArgs<IEvent> e)
        {
            switch (e.Action)
            {
                case ListsCompareResult.ElementMissingInFirstList:
                    CounterElementMissingInFirstList++;
                    break;
                case ListsCompareResult.ElementMissingInSecondList:
                    CounterElementMissingInSecondList++;
                    break;
                case ListsCompareResult.ElementIsInBothLists:
                    CounterElementIsInBothLists++;
                    break;
                default:
                    break;
            }
        }

        private static CalendarService GetService()
        {
            CalendarService myService = new CalendarService("CalendarTest");
            myService.setUserCredentials(ConfigurationManager.AppSettings["GoogleUser"], ConfigurationManager.AppSettings["GooglePassword"]);
            return myService;
        }

        private static string GetFeedID()
        {
            return ConfigurationManager.AppSettings["GoogleCalendarId"];
        }


        private static DataTable NewDataTable()
        {
            var dt = new DataTable();
            dt.Columns.Add("Id", typeof(int));
            dt.Columns.Add("Title", typeof(string));
            dt.Columns.Add("Content", typeof(string));
            dt.Columns.Add("Location", typeof(string));
            dt.Columns.Add("Start", typeof(DateTime));
            dt.Columns.Add("End", typeof(DateTime));
            dt.Columns.Add("AllDay", typeof(bool));
            dt.Columns.Add("Version", typeof(string));
            return dt;
        }

        private static DataTable FillEventTable(int count)
        {
            return FillEventTable(0, count);
        }
        private static DataTable FillEventTable(int start, int count)
        {
            return FillEventTable(start, count, false);
        }

        private static DataTable FillEventTable(int start, int count, bool noEndDate)
        {
            var dt = NewDataTable();
            for (int i = start; i < start + count; i++)
            {
                var dr = dt.NewRow();
                dr["Id"] = i;
                dr["Title"] = "Title " + i.ToString();
                dr["Content"] = "Content " + i.ToString();
                dr["Location"] = "Location " + i.ToString();
                dr["Start"] = DateTime.Today.AddDays(i);
                if (!noEndDate) dr["End"] = DateTime.Today.AddDays(i + 1);
                dr["AllDay"] = true;
                dt.Rows.Add(dr);
            }
            return dt;
        }
        #endregion
    }
}
